package cn.edu.sgu.www.mhxysy.service.qiling.impl;

import cn.edu.sgu.www.mhxysy.vo.Imager;
import cn.edu.sgu.www.mhxysy.pager.Pager;
import cn.edu.sgu.www.mhxysy.consts.CustomMessages;
import cn.edu.sgu.www.mhxysy.dto.qiling.QilingDTO;
import cn.edu.sgu.www.mhxysy.entity.equipment.Equipment;
import cn.edu.sgu.www.mhxysy.entity.qiling.Qiling;
import cn.edu.sgu.www.mhxysy.entity.qiling.QilingAttribute;
import cn.edu.sgu.www.mhxysy.entity.qiling.QilingCategory;
import cn.edu.sgu.www.mhxysy.enums.InlayStatus;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import cn.edu.sgu.www.mhxysy.function.computer.score.impl.QilingScoreComputer;
import cn.edu.sgu.www.mhxysy.mapper.equipment.EquipmentMapper;
import cn.edu.sgu.www.mhxysy.mapper.equipment.EquipmentTypeMapper;
import cn.edu.sgu.www.mhxysy.mapper.qiling.QilingAttributeMapper;
import cn.edu.sgu.www.mhxysy.mapper.qiling.QilingCategoryMapper;
import cn.edu.sgu.www.mhxysy.mapper.qiling.QilingMapper;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.service.qiling.QilingService;
import cn.edu.sgu.www.mhxysy.util.ObjectUtils;
import cn.edu.sgu.www.mhxysy.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Service
public class QilingServiceImpl implements QilingService {

	private final QilingMapper qilingMapper;
	private final EquipmentMapper equipmentMapper;
	private final EquipmentTypeMapper equipmentTypeMapper;
	private final QilingScoreComputer qilingScoreComputer;
	private final QilingCategoryMapper qilingCategoryMapper;
	private final QilingAttributeMapper qilingAttributeMapper;

	@Autowired
	public QilingServiceImpl(
			QilingMapper qilingMapper,
			EquipmentMapper equipmentMapper,
			EquipmentTypeMapper equipmentTypeMapper,
			QilingScoreComputer qilingScoreComputer,
			QilingCategoryMapper qilingCategoryMapper,
			QilingAttributeMapper qilingAttributeMapper) {
		this.qilingMapper = qilingMapper;
		this.equipmentMapper = equipmentMapper;
		this.equipmentTypeMapper = equipmentTypeMapper;
		this.qilingScoreComputer = qilingScoreComputer;
		this.qilingCategoryMapper = qilingCategoryMapper;
		this.qilingAttributeMapper = qilingAttributeMapper;
	}

	@Override
	public void compute(String qilingId) {
		UpdateWrapper<Qiling> updateWrapper = new UpdateWrapper<>();

		updateWrapper.eq("id", qilingId);
		updateWrapper.set("score", qilingScoreComputer.compute(qilingId));

		qilingMapper.update(updateWrapper.getEntity(), updateWrapper);
	}

	@Override
	public String inlay(String qilingId, String equipmentId) {
		Qiling qiling = qilingMapper.selectById(qilingId);
		Integer inlayStatus = qiling.getInlayStatus();

		// 状态为0-未镶嵌，操作为【镶嵌】
		if (InlayStatus.WXQ.getValue().equals(inlayStatus)) { // 镶嵌
			// 验证器灵和装备是否搭配
			Equipment equipment = equipmentMapper.selectById(equipmentId);
			QilingCategory qilingCategory = qilingCategoryMapper.selectById(qiling.getCategoryId());

			if (!equipment.getCategoryId().equals(qilingCategory.getEquipmentId())) {
				throw new GlobalException(ResponseCode.FORBIDDEN, "器灵不适合该装备");
			}

			// 验证该装备是否镶嵌了的器灵
			QueryWrapper<Qiling> queryWrapper = new QueryWrapper<>();

			queryWrapper.eq("equipment_id", equipmentId);

			long count = qilingMapper.selectCount(queryWrapper);

			if (count >= 1) {
				throw new GlobalException(ResponseCode.CONFLICT, "此装备已经镶嵌了器灵！");
			}

			UpdateWrapper<Qiling> updateWrapper = new UpdateWrapper<>();

			updateWrapper.eq("id", qilingId);
			updateWrapper.set("inlay_status", InlayStatus.WXQ.getValue());

			// 设置set子句：set equipment_id = null, inlay_status = 0
			updateWrapper.set("equipment_id", equipmentId);
			updateWrapper.set("inlay_status", InlayStatus.YXQ.getValue());

			qilingMapper.update(updateWrapper.getEntity(), updateWrapper);
		} else { // 取下
			UpdateWrapper<Qiling> updateWrapper = new UpdateWrapper<>();

			updateWrapper.eq("id", qilingId);

			// 设置set子句：set equipment_id = null, inlay_status = 0
			updateWrapper.set("equipment_id", null);
			updateWrapper.set("inlay_status", InlayStatus.WXQ.getValue());

			qilingMapper.update(updateWrapper.getEntity(), updateWrapper);
		}

		String[] operationArray = {"镶嵌", "取下"};

		return operationArray[inlayStatus];
	}

	@Override
	public void insert(QilingDTO qilingDTO) {
		Qiling qiling = toEntity(qilingDTO);

		qiling.setId(qiling.uuid());
		qiling.setEquipmentId(null);
		qiling.setInlayStatus(InlayStatus.WXQ.getValue());

		qilingMapper.insert(qiling);
	}

	@Override
	public void deleteById(String qilingId) {
		// 1、删除器灵属性
		QueryWrapper<QilingAttribute> queryWrapper = new QueryWrapper<>();

		queryWrapper.eq("qiling_id", qilingId);

		qilingAttributeMapper.delete(queryWrapper);

		// 2、删除器灵
		qilingMapper.deleteById(qilingId);
	}

	@Override
	public void updateById(QilingDTO qilingDTO) {
		ObjectUtils.requireNonNull(qilingDTO.getId(), CustomMessages.ID_NOT_NULL);

		Qiling qiling = toEntity(qilingDTO);

		qilingMapper.updateById(qiling);
	}

	@Override
	public Qiling selectById(String id) {
		return qilingMapper.selectById(id);
	}

	@Override
	public Imager selectImage(String equipmentId) {
		return qilingMapper.selectImage(equipmentId);
	}

	@Override
	public Qiling selectByEquipmentId(String equipmentId) {
		QueryWrapper<Qiling> queryWrapper = new QueryWrapper<>();

		queryWrapper.eq("equipment_id", equipmentId);

		return qilingMapper.selectOne(queryWrapper);
	}

	@Override
	public Page<Qiling> selectByPage(Pager<Qiling> pager) {
		QueryWrapper<Qiling> queryWrapper = Pager.getQueryWrapper(pager, true);
		Page<Qiling> page = Pager.ofPage(pager);

		return qilingMapper.selectPage(page, queryWrapper);
	}

	@Override
	public List<Qiling> selectList(String roleId, Integer equipmentId) {
		if (StringUtils.isNotEmpty(roleId) && equipmentId != null) {
			Integer type = equipmentTypeMapper.selectTopType(equipmentId);

			return qilingMapper.select(type, roleId, equipmentId);
		}

		return new ArrayList<>();
	}

	private Qiling toEntity(QilingDTO qilingDTO) {
		Qiling qiling = new Qiling();

		qiling.setId(qilingDTO.getId());
		qiling.setScore(qilingDTO.getScore());
		qiling.setForger(qilingDTO.getForger());
		qiling.setRoleId(qilingDTO.getRoleId());
		qiling.setCategoryId(qilingDTO.getCategoryId());
		qiling.setTaozhuangId(qilingDTO.getTaozhuangId());

		return qiling;
	}

}